<?php 


include_once($CFG->dirroot . '/mercurius/actions.php');
include_once($CFG->dirroot . '/mercurius/rsslib.php');
include_once($CFG->dirroot . '/mercurius/amCharts/lib.php');

define('CALENDAR_DEFAULT_STARTING_WEEKDAY',   1);

// Fetch the correct values from admin settings/lang pack
// If no such settings found, use the above defaults
$firstday = isset($CFG->calendar_startwday) ? $CFG->calendar_startwday : get_string('firstdayofweek');
if(!is_numeric($firstday)) {    
    define ('CALENDAR_STARTING_WEEKDAY', CALENDAR_DEFAULT_STARTING_WEEKDAY);
}
else {
    define ('CALENDAR_STARTING_WEEKDAY', intval($firstday) % 7);
}


if (!defined('MOODLE_INTERNAL')) {
	die('Direct access to this script is forbidden.');    ///  It must be included from a Moodle page
}

function uuid()
{
    // version 4 UUID
    return sprintf(
        '%08x-%04x-%04x-%02x%02x-%012x',
        mt_rand(),
        mt_rand(0, 65535),
        bindec(substr_replace(
            sprintf('%016b', mt_rand(0, 65535)), '0100', 11, 4)
        ),
        bindec(substr_replace(sprintf('%08b', mt_rand(0, 255)), '01', 5, 2)),
        mt_rand(0, 255),
        mt_rand()
    );
}

function formattime($val) {

	$ptrn1 = "/(^[0-9]{0,2}$)/i";  // seconds
	$ptrn2 = "/(^[0-9]{0,2}):([0-9]{0,2}$)/i";  // minutes:seconds
	$ptrn3 = "/(^[0-9]{0,5}):([0-9]{0,2}):([0-9]{0,2}$)/i"; //hours:minutes:seconds
	$ptrn4 = "/(^[0-9]{1}):?([0-9]{0,2}$)/i"; // minutes:seconds
	$ptrn5 = "/(^[0-9]{0,2}):?([0-9]{0,2}$)/i"; // minutes:seconds
	$ptrn6 = "/(^[0-9]{1}):?([0-9]{0,2}):?([0-9]{0,2}$)/i"; // hours:minutes:seconds
	$ptrn7 = "/(^[0-9]{0,5}):?([0-9]{0,2}):?([0-9]{0,2}$)/i";  // hours:minutes:seconds

	$matches = array ();

	preg_match($ptrn1, $val, $count1);
	preg_match($ptrn2, $val, $count2);
	preg_match($ptrn3, $val, $count3);
	preg_match($ptrn4, $val, $count4);
	preg_match($ptrn5, $val, $count5);
	preg_match($ptrn6, $val, $count6);
	preg_match($ptrn7, $val, $count7);

	if (count($count1) > 0) {
		preg_match($ptrn1, $val, $matches);

		if (!$matches[1])
			$matches[1] = "0";
		if (!is_numeric($matches[1]) or $matches[1] >= 60)
			return "";

		return "00:00:" . sprintf("%02.0f", $matches[1]);

	} else
		if (count($count2) > 0) {
			preg_match($ptrn2, $val, $matches);
			if (!$matches[1])
				$matches[1] = "0";
			if (!$matches[2])
				$matches[2] = "0";
			if (!is_numeric($matches[1]) or $matches[1] >= 60)
				return "";
			if (!is_numeric($matches[2]) or $matches[2] >= 60)
				return "";
			return "00:" . sprintf("%02.0f", $matches[1]) . ":" . sprintf("%02.0f", $matches[2]);
		} else
			if (count($count3) > 0) {
				preg_match($ptrn3, $val, $matches);
				if (!$matches[1])
					$matches[1] = "0";
				if (!$matches[2])
					$matches[2] = "0";
				if (!$matches[3])
					$matches[3] = "0";

				if (!is_numeric($matches[1]) )
					return "";
				if (!is_numeric($matches[2]) or $matches[2] >= 60)
					return "";
				if (!is_numeric($matches[3]) or $matches[3] >= 60)
					return "";
				return sprintf("%02.0f", $matches[1]) . ":" . sprintf("%02.0f", $matches[2]) . ":" . sprintf("%02.0f", $matches[3]);
			} else
				if (count($count4) > 0) {
					preg_match($ptrn4, $val, $matches);

					if (!$matches[1])
						if (!$matches[2])
							$matches[1] = "0";
					$matches[2] = "0";

					if (!is_numeric($matches[1]) or $matches[1] >= 60)
						return "";
					if (!is_numeric($matches[2]) or $matches[2] >= 60)
						return "";
					return "00:" . sprintf("%02.0f", $matches[1]) . ":" . sprintf("%02.0f", $matches[2]);
				} else
					if (count($count5) > 0) {
						preg_match($ptrn5, $val, $matches);

						if (!$matches[1])
							$matches[1] = "0";
						if (!$matches[2])
							$matches[2] = "0";

						if (!is_numeric($matches[1]) or $matches[1] >= 60)
							return "";
						if (!is_numeric($matches[2]) or $matches[2] >= 60)
							return "";
						return "00:" . sprintf("%02.0f", $matches[1]) . ":" . sprintf("%02.0f", $matches[2]);
					} else
						if (count($count6) > 0) {
							preg_match($ptrn6, $val, $matches);

							if (!$matches[1])
								$matches[1] = "0";
							if (!$matches[2])
								$matches[2] = "0";
							if (!$matches[3])
								$matches[3] = "0";

							if (!is_numeric($matches[1]) )
								return "";
							if (!is_numeric($matches[2]) or $matches[2] >= 60)
								return "";
							if (!is_numeric($matches[3]) or $matches[3] >= 60)
								return "";
							return sprintf("%02.0f", $matches[1]) . ":" . sprintf("%02.0f", $matches[2]) . ":" . sprintf("%02.0f", $matches[3]);
						} else
							if (count($count7) > 0) {
								preg_match($ptrn7, $val, $matches);

								if (!$matches[1])
									$matches[1] = "0";
								if (!$matches[2])
									$matches[2] = "0";
								if (!$matches[3])
									$matches[3] = "0";

								if (!is_numeric($matches[1]) )
									return "";
								if (!is_numeric($matches[2]) or $matches[2] >= 60)
									return "";
								if (!is_numeric($matches[3]) or $matches[3] >= 60)
									return "";
								return sprintf("%02.0f", $matches[1]) . ":" . sprintf("%02.0f", $matches[2]) . ":" . sprintf("%02.0f", $matches[3]);
							} 

}

function get_mercurius_user($USER) {
	if(is_numeric($USER)) { // is id
	$USER = get_record('user', 'id', $USER);
	$USER = get_complete_user_data('username',$USER->username);
	} 
	
	if(!isset($USER->id)) {
		print_header_simple("",'heading', 'home');
		error("Invalid feed key");
	}
	
	if(!record_exists('mercurius','name',"version")) {
		return $USER;  // Mercurius is not configured, let the index.php take care of the installation.
	}
	
	if(!record_exists('mercurius_user_settings','userid',$USER->id)) {
		return $USER; // Mercurius user is not configured, let the index.php take care of it.
	}
	
	
	$user =  (array) get_record("mercurius_user_settings", "userid", $USER->id);
	
	if(count($user) == 1) {
		return $user;
	}
	
	foreach ($user as $variable => $value) {
		if($variable != 'id') {
			if($value == null) {
				$value = "";
			}
			$USER->$variable = $value;
        }
    }
	
	$USER->age = getAge($USER->dob);
	return $USER;
}

function get_user_from_feed_key($key) {
	$user = get_record("mercurius_user_settings", "feed_key", $key);
	if(!isset($user->id)) {
		print_header_simple("",'heading', 'home');
		error("Invalid feed key");
	}
	return get_mercurius_user($user->userid);
}

function get_user_from_adminfeed_key($key) {
	$user = get_record("mercurius_user_settings", "adminfeed_key", $key);
	if(!isset($user->id)) {
		print_header_simple("",'heading', 'home');
		error("Invalid feed key");
	}
	return get_mercurius_user($user->userid);
}

function getAge($date) {
	$date = is_string($date) ? strtotime($date) : $date;   
      $secondsSince = time() - $date;
      $secondsInAYear = 31556926;
      $yearsSince = floor($secondsSince / $secondsInAYear);
      return $yearsSince; 
}

function getUserAge($user = null) {
	global $USER,$CFG;
	
	if($user == NULL) {
		$user = $USER;
	}
	
	return getAge($user->dob);
}

function isUserMale($user = null) {
	global $USER,$CFG;
	
	if($user == NULL) {
		$user = $USER;
	}
	
	if($user->gender == 1) {
		return true;
	} else {
		return false;
	}
}


function getUserWeight($user = null,$metric=true) {
	global $USER,$CFG;
	
	if($user == NULL) {
		$user = $USER;
	}
	
	
	// Get last inserted weight and convert it to the correct measurement
	$record = get_record_sql("SELECT weight,weight_unit FROM {$CFG->prefix}mercurius_measurement_log  WHERE user = {$user->id} ORDER BY date desc ",true);
	
	if($metric) {
		if($record->weight_unit == 'lbs') {
			return $record->weight * 0.45359237;
		} else {
			return $record->weight;
		}
	} else {
		if($record->weight_unit == 'kg') {
			return $record->weight;
		} else {
			return $record->weight * 2.20462262;
		}
	}
}

function getHRMax($user = NULL) {
	global $USER,$CFG;
	
	if($user == NULL) {
		$user = $USER;
	}
	
	
	/*
 	 * From Wikipedia: A 2002 study (reference below) of 43 different 
 	 * formulae for HRmax (including the one above) concluded the following:
 	 * 1) No "acceptable" formula currently existed, 
 	 * (they used the term "acceptable" to mean acceptable for both prediction of VO_2 max, and prescription of exercise training HR ranges)
 	 * 2) The most accurate formula of those examined was:
 	 * 		HRmax = 205.8 ? (0.685 * age)
 	 * 
 	 * This was found to have a Standard Deviation that, although 
 	 * large (6.4 bpm), was still deemed to be acceptable for the use of prescribing exercise training HR ranges. 
 	 * 
 	 * Robergs, Robert A. & Landwehr, Roberto (May 2002), 
 	 * "The Surprising History of the "HRmax=220-age" Equation", Journal of Exercise Physiology online 5 (2), 
 	 * ISSN 1097-9751, <http://faculty.css.edu/tboone2/asep/Robergs2.pdf>. Retrieved on 28 February 2008
 	 */	 	
	 
	 $default = 0;
	 if(isset($user->dob) and !empty($user->dob)) {
	 	$default = round(205.8 - (0.685 * getAge($user->dob)));
	 }

	 if(!isset($user->hr_max) or empty($user->hr_max)) {
	 	return "$default";
	 } else if(isset($user->hr_max) and empty($user->hr_max)) {
	 	return "$default";
	 } if(isset($user->hr_max)) {
	 	return "{$user->hr_max}";
	 } else {
	 	return "";
	 }
}

function getVo2Max($user = NULL) {
	global $USER,$CFG;
	
	if($user == NULL) {
		$user = $USER;
	}
	 
	 $default = 0;
	 
	 if(!isset($user->vo2_max) or empty($user->vo2_max)) {
	 	return "$default";
	 } else if(isset($user->vo2_max) and empty($user->vo2_max)) {
	 	return "$default";
	 } if(isset($user->vo2_max)) {
	 	return "{$user->vo2_max}";
	 } else {
	 	return "";
	 }
	
}

function generateMapData($id=NULL) {
	global $USER, $CFG;
	
	return generateData($id,'2');
}

function generateHRData($id=NULL) {
	global $USER, $CFG;
	return generateData($id,'0');
}


function generateData($id=NULL,$type) {
	global $USER, $CFG;
	
	if(empty($id)) {
		$id   = required_param('id');
	}
	
	if(is_numeric($id) and
		record_exists('mercurius_exercise_log','id',$id,'user',$USER->id) and
		record_exists('mercurius_exercise_data','session_prkey',$id,'Data_type',$type)
		) {

		$sql = "SELECT * FROM `{$CFG->prefix}mercurius_exercise_data` where session_prkey = $id and Data_type = $type ";
		if($type == '2') {
			$sql .= "group by `lat`,`lon` ";
		} 
		$sql .= "order by `cum_duration` asc ";

		$ret = get_records_sql($sql);
		
		$track = "";
		$log = get_record('mercurius_exercise_log','id',$id);
		
		if(empty($log->title)) {
			$log->title = $log->activity;
		}
		
		if(!empty($log->distance) and !empty($log->distance_unit)) {
			$log->title = $log->title . " (" . $log->distance . " " . $log->distance_unit . ")";
		}
		
		$log->datetime = is_string($log->datetime) ? strtotime($log->datetime) : $log->datetime; 
		
		$track->name = $log->title;
		$track->data = $ret;
		$track->log = $log;
		$track->starttime = date('c', $log->datetime);
		if($type == '2') {
			$track->center = get_session_data_center($id);
		}

		return $track;
	} else {
		print_header_simple("",'heading', 'home');
		error("Invalid ID: " . $id);
		die;
	}
}


function time_to_minutes($time) {
	$array = explode(":", formattime($time));	
	return $array[0] * 60 + $array[1];
}

function seconds_to_time($time_in_seconds) {
	return formattime(Duration::toString($time_in_seconds,array('hours'=>3600,'minutes'=>60,'seconds'=>1),":",false,true));
}

function calculate_points($log,$zone=NULL) {
	$points = 0;
	if(empty($zone)) {
		$points = 	time_to_minutes($log->z1_time) * 1 + 
					time_to_minutes($log->z2_time) * 2 +
					time_to_minutes($log->z3_time) * 3 +
					time_to_minutes($log->z4_time) * 4 +
					time_to_minutes($log->z5_time) * 5;
	} else if($zone == 1 or $zone == 2 or $zone == 3 or $zone == 4 or $zone == 5) {
		$zonetime = "z{$zone}_time";
		$points = time_to_minutes($log->$zonetime) * $zone;
	}
	return $points;
}

function calculate_bmr_calories() {
	
	/*
	 * A new predictive equation for resting energy expenditure in healthy individuals

MD Mifflin, ST St Jeor, LA Hill, BJ Scott, SA Daugherty and YO Koh
Nutrition Education and Research Program, University of Nevada School of Medicine, Reno 89557. 

 h = (9.99\cdot weight)+(6.25\cdot height)-(4.92\cdot age)+166\cdot sex (1 for males; 0 for females)-161


	 */
}

function calculate_zone_calories($log,$zone) {
	global $CFG,$USER;

	/*
	 * Prediction of energy expenditure from heart rate monitoring during submaximal exercise" 
	 * by L. R. KEYTEL, J. H. GOEDECKE, T. D. NOAKES, H. HIILOSKORPI, R. LAUKKANEN, L. VAN DER MERWE, & E. V. LAMBERT 
	 * that was published in the Journal of Sports Sciences
	 * 
	 *  Using VO2max
		Men: C/min = (-59.3954 + (-36.3781 + 0.271 x age + 0.394 x weight +
		0.404 x VO2max + 0.634 x HR))/4.184
		Women: C/min = (-59.3954 + (0.274 x age + 0.103 x weight + 0.380 x
		VO2max + 0.450 x HR)) / 4.184
		
		Without VO2max
		Men: C/min = (-55.0969 + 0.6309 x HR + 0.1988 x weight + 0.2017 x age) / 4.184
		Women: C/min = (-20.4022 + 0.4472 x HR - 0.1263 x weight + 0.074 x age) / 4.184
		weight is in kg
		
		Should probably improve method since this is being calculated based on the zone average and not the per HR minute average.
	 */
	
	$calories = 0;
	$vo2 = getVo2Max();
	$age = getUserAge();
	$weight = getUserWeight(); // Returns weight in kg.
	$male = isUserMale();
	$hrmax = getHRMax();
	
	if($male) {
		if(empty($vo2)) {
			if($zone == 1) {
				$calories += ((-55.0969 + 0.6309 * ($hrmax * .55) + 0.1988 * $weight + 0.2017 * $age) / 4.184) * time_to_minutes($log->z1_time); // Avg at Z1 (55% of HR Max)
			} else if($zone == 2) {
				$calories += ((-55.0969 + 0.6309 * ($hrmax * .65) + 0.1988 * $weight + 0.2017 * $age) / 4.184) * time_to_minutes($log->z2_time); // Avg at Z2 (65% of HR Max)
			} else if($zone == 3) {
				$calories += ((-55.0969 + 0.6309 * ($hrmax * .75) + 0.1988 * $weight + 0.2017 * $age) / 4.184) * time_to_minutes($log->z3_time); // Avg at Z3 (75% of HR Max)
			} else if($zone == 4) {
				$calories += ((-55.0969 + 0.6309 * ($hrmax * .85) + 0.1988 * $weight + 0.2017 * $age) / 4.184) * time_to_minutes($log->z4_time); // Avg at Z4 (85% of HR Max)
			} else if($zone == 5) {
				$calories += ((-55.0969 + 0.6309 * ($hrmax * .95) + 0.1988 * $weight + 0.2017 * $age) / 4.184) * time_to_minutes($log->z5_time); // Avg at Z5 (95% of HR Max)
			} else {
				$calories = 0;
			}
		} else {
			if($zone == 1) {
				$calories += ((-59.3954 + (-36.3781 + 0.271 * $age + 0.394 * $weight + 0.404 * $vo2 + 0.634 * ($hrmax * .55)))/4.184) * time_to_minutes($log->z1_time); // Avg at Z1 (55% of HR Max)
			} else if($zone == 2) {
				$calories += ((-59.3954 + (-36.3781 + 0.271 * $age + 0.394 * $weight + 0.404 * $vo2 + 0.634 * ($hrmax * .65)))/4.184) * time_to_minutes($log->z2_time); // Avg at Z2 (65% of HR Max)
			} else if($zone == 3) {
				$calories += ((-59.3954 + (-36.3781 + 0.271 * $age + 0.394 * $weight + 0.404 * $vo2 + 0.634 * ($hrmax * .75)))/4.184) * time_to_minutes($log->z3_time); // Avg at Z3 (75% of HR Max)
			} else if($zone == 4) {
				$calories += ((-59.3954 + (-36.3781 + 0.271 * $age + 0.394 * $weight + 0.404 * $vo2 + 0.634 * ($hrmax * .85)))/4.184) * time_to_minutes($log->z4_time); // Avg at Z4 (85% of HR Max)
			} else if($zone == 5) {
				$calories += ((-59.3954 + (-36.3781 + 0.271 * $age + 0.394 * $weight + 0.404 * $vo2 + 0.634 * ($hrmax * .95)))/4.184) * time_to_minutes($log->z5_time); // Avg at Z5 (95% of HR Max)
			}
		}
	} else {
		if(empty($vo2)) {
			if($zone == 1) {
				$calories += ((-20.4022 + 0.4472 * ($hrmax * .55) - 0.1263 * $weight + 0.074 * $age) / 4.184) * time_to_minutes($log->z1_time); // Avg at Z1 (55% of HR Max)
			} else if($zone == 2) {
				$calories += ((-20.4022 + 0.4472 * ($hrmax * .65) - 0.1263 * $weight + 0.074 * $age) / 4.184) * time_to_minutes($log->z2_time); // Avg at Z2 (65% of HR Max)
			} else if($zone == 3) {
				$calories += ((-20.4022 + 0.4472 * ($hrmax * .75) - 0.1263 * $weight + 0.074 * $age) / 4.184) * time_to_minutes($log->z3_time); // Avg at Z3 (75% of HR Max)
			} else if($zone == 4) {
				$calories += ((-20.4022 + 0.4472 * ($hrmax * .85) - 0.1263 * $weight + 0.074 * $age) / 4.184) * time_to_minutes($log->z4_time); // Avg at Z4 (85% of HR Max)
			} else if($zone == 5) {
				$calories += ((-20.4022 + 0.4472 * ($hrmax * .95) - 0.1263 * $weight + 0.074 * $age) / 4.184) * time_to_minutes($log->z5_time); // Avg at Z5 (95% of HR Max)
			}
		} else {
			if($zone == 1) {
				$calories += ((-59.3954 + (0.274 * $age + 0.103 * $weight + 0.380 * $vo2 + 0.450 * ($hrmax * .55))) / 4.184) * time_to_minutes($log->z1_time); // Avg at Z1 (55% of HR Max)
			} else if($zone == 2) {
				$calories += ((-59.3954 + (0.274 * $age + 0.103 * $weight + 0.380 * $vo2 + 0.450 * ($hrmax * .65))) / 4.184) * time_to_minutes($log->z2_time); // Avg at Z2 (65% of HR Max)
			} else if($zone == 3) {
				$calories += ((-59.3954 + (0.274 * $age + 0.103 * $weight + 0.380 * $vo2 + 0.450 * ($hrmax * .75))) / 4.184) * time_to_minutes($log->z3_time); // Avg at Z3 (75% of HR Max)
			} else if($zone == 4) {
				$calories += ((-59.3954 + (0.274 * $age + 0.103 * $weight + 0.380 * $vo2 + 0.450 * ($hrmax * .85))) / 4.184) * time_to_minutes($log->z4_time); // Avg at Z4 (85% of HR Max)
			} else if($zone == 5) {
				$calories += ((-59.3954 + (0.274 * $age + 0.103 * $weight + 0.380 * $vo2 + 0.450 * ($hrmax * .95))) / 4.184) * time_to_minutes($log->z5_time); // Avg at Z5 (95% of HR Max)
			}
		}
	}
	
	return round($calories);
}

function calculate_calories($log) {
	global $CFG,$USER;

	$calories = calculate_zone_calories($log,1) + calculate_zone_calories($log,2) +
				 calculate_zone_calories($log,3) + calculate_zone_calories($log,4) + calculate_zone_calories($log,5);
	return $calories;
}

function get_exercise_session_data($id) {
	global $CFG;
	
	$sql = "SELECT * FROM `{$CFG->prefix}mercurius_exercise_data` where session_prkey = $id and Data_type = 2 group by `lat`,`lon` order by `cum_duration` asc ";
	return get_records_sql($sql);
}

function get_session_data_center($id) {
	global $CFG;
	
	$sql = "SELECT min(lat) + ((max(lat) - min(lat)) / 2) as centerlat, " .
			"min(lon) + ((max(lon) - min(lon)) / 2) as centerlon " .
			"FROM `{$CFG->prefix}mercurius_exercise_data` where session_prkey = $id and " .
			" Data_type = 2 order by `cum_duration` asc ";
			
	$centercords = get_record_sql($sql);
	$val = "";
	
	$val->lat =  number_format($centercords->centerlat,5);
	$val->lon = number_format($centercords->centerlon,5);
	return $val;
}

function get_exercise_log_stats($start,$end) {
	global $CFG,$USER;
	
	$sql = "select " .
				"ROUND(( " .
					"SUM(TIME_TO_SEC(z1_time)) * 1 * (1/60.0)  + " .
					"SUM(TIME_TO_SEC(z2_time)) * 2 * (1/60.0)  + " .
					"SUM(TIME_TO_SEC(z3_time)) * 3 * (1/60.0)  + " .
					"SUM(TIME_TO_SEC(z4_time)) * 4 * (1/60.0)  + " .
					"SUM(TIME_TO_SEC(z5_time)) * 5 * (1/60.0) )) as total_points, " .
				"( " .
					"SUM(TIME_TO_SEC(z1_time)) + " .
					"SUM(TIME_TO_SEC(z2_time)) + " .
					"SUM(TIME_TO_SEC(z3_time)) + " .
					"SUM(TIME_TO_SEC(z4_time)) + " .
					"SUM(TIME_TO_SEC(z5_time))) as total_zone_seconds, " .
				"ROUND(SUM(TIME_TO_SEC(z1_time)) * 1 * (1/60.0)) as z1_points,  " .
				"ROUND(SUM(TIME_TO_SEC(z2_time)) * 2 * (1/60.0)) as z2_points,  " .
				"ROUND(SUM(TIME_TO_SEC(z3_time)) * 3 * (1/60.0)) as z3_points,  " .
				"ROUND(SUM(TIME_TO_SEC(z4_time)) * 4 * (1/60.0)) as z4_points,  " .
				"ROUND(SUM(TIME_TO_SEC(z5_time)) * 5 * (1/60.0)) as z5_points,  " .
				"SUM(TIME_TO_SEC(z1_time)) as z1_seconds,  " .
				"SUM(TIME_TO_SEC(z2_time)) as z2_seconds,  " .
				"SUM(TIME_TO_SEC(z3_time)) as z3_seconds,  " .
				"SUM(TIME_TO_SEC(z4_time)) as z4_seconds,  " .
				"SUM(TIME_TO_SEC(z5_time)) as z5_seconds, " .
				"SUM(TIME_TO_SEC(duration)) as total_duration_seconds " .
 	"from {$CFG->prefix}mercurius_exercise_log where date >= '$start' AND date <= '$end' AND user={$USER->id}";
	
	$record = get_record_sql($sql);
	
	if(empty($record->total_points)) $record->total_points = 0;
	if(empty($record->z1_points)) $record->z1_points = 0;
	if(empty($record->z2_points)) $record->z2_points = 0;
	if(empty($record->z3_points)) $record->z3_points = 0;
	if(empty($record->z4_points)) $record->z4_points = 0;
	if(empty($record->z5_points)) $record->z5_points = 0;
	
	$record->z1_time = seconds_to_time($record->z1_seconds);
	$record->z2_time = seconds_to_time($record->z2_seconds);
	$record->z3_time = seconds_to_time($record->z3_seconds);
	$record->z4_time = seconds_to_time($record->z4_seconds);
	$record->z5_time = seconds_to_time($record->z5_seconds);

	return $record;
}

function get_map_sessions($u=null) {
	
	global $USER,$CFG;
	
	$user = $USER;
	
	if(!empty($u)) {
		$user = $u;
	}
	
	$sql = "SELECT DISTINCT data.session_prkey FROM `{$CFG->prefix}mercurius_exercise_data` data, `{$CFG->prefix}mercurius_exercise_log` log, `{$CFG->prefix}mercurius_user_settings` user where data.session_prkey = log.id and log.user = {$user->id} and data.Data_type = 2 order by log.date desc, data.cum_duration asc ";
	
	return get_records_sql($sql);
}

function has_map_sessions($id) {
	global $CFG;

	
	$sql = "SELECT COUNT(data.session_prkey) FROM `{$CFG->prefix}mercurius_exercise_data` data, `{$CFG->prefix}mercurius_exercise_log` log where data.session_prkey = log.id and log.id={$id} and data.Data_type = 2 order by data.cum_duration asc ";
	
	if(count_records_sql($sql) > 0) {
		return true;
	} else {
		return false;
	}
}

function rndm_color_code($b_safe = TRUE) {
    
    //make sure the parameter is boolean
    if(!is_bool($b_safe)) {return FALSE;}
    
    //if a browser safe color is requested then set the array up
    //so that only a browser safe color can be returned
    if($b_safe) {
        $ary_codes = array('00','33','66','99','CC','FF');
        $max = 5; //the highest array offest
    //if a browser safe color is not requested then set the array
    //up so that any color can be returned.
    } else {
        $ary_codes = array();
        for($i=0;$i<16;$i++) {
            $t_1 = dechex($i);
            for($j=0;$j<16;$j++) {
                $t_2 = dechex($j);
                $ary_codes[] = "$t_1$t_2";
            } //end for j
        } //end for i
        $max = 256; //the highest array offset
    } //end if
    
    $retVal = '';
    
    //generate a random color code
    for($i=0;$i<3;$i++) {
        $offset = rand(0,$max);
        $retVal .= $ary_codes[$offset];
    } //end for i
    
    return $retVal;
} //end rndm_color_code

function clean_exercise_log($log) {
	if($log->datetime != '0000-00-00 00:00:00') {
		$log->datetime = date('h:i:s A', strtotime($log->datetime));
	} else {
		$log->datetime = "N/A";				
	}
	
	// formattime
	if(isset($log->duration)) {
		$log->duration = formattime($log->duration);
	}
	
	if(isset($log->z1_time)) {
		$log->z1_time = formattime($log->z1_time);
	}
	
	if(isset($log->z2_time)) {
		$log->z2_time = formattime($log->z2_time);
	}
	
	if(isset($log->z3_time)) {
		$log->z3_time = formattime($log->z3_time);
	}
	
	if(isset($log->z4_time)) {
		$log->z4_time = formattime($log->z4_time);
	}
	
	if(isset($log->z5_time)) {
		$log->z5_time = formattime($log->z5_time);
	}
}

function generate_summary($log,$feed_action,$has_map_sessions=false) {
	$summary = "";
	
	if(empty($log->title)) {
			$log->title = 'Untitled ';
			if($log->activity) {
				$log->title .= ' --- ' . $log->activity;
			}
		}
		
		
		if(!empty($log->distance) and $log->distance > 0 and !empty($log->distance_unit)) {
			$log->title .= " (" . $log->distance . " " . $log->distance_unit . ")";
		}


		if($feed_action != 'mapFeed' and $has_map_sessions) {
			$log->title .= " -- [GPS]";
		}
		
		
		
		$dist = $log->distance;
		if($log->distance_unit) {
			$dist .= " " . $log->distance_unit;
		}
		
		
		
		$table = new stdClass();
	  	//$table->align = array('left', 'left');
	    $table->size = array('', '','20px', '', '','');
	    $table->width = '*';
	    $table->data = array();
		$table->class = '';
		$table->extra_attrs = "border=\"0\" style=\"color: #555555; font-size: 12px;font-family: Arial, sans-serif;line-height: 16px;";
		$table->data[] = array(
								'Activity:','<b>'.$log->activity.'</b>',
								'','', 
								'Total Points:','<b>'.calculate_points($log).'</b>',
							);
		$table->data[] = array(
								'Date:','<b>'.$log->date.'</b>', 
								'','',
								'Time:','<b>'.$log->datetime.'</b>', 
							);
		$table->data[] = array(
								'Duration:','<b>'.$log->duration.'</b>',  
								'','',
								'Distance:','<b>'.$dist.'</b>', 
							);
		$table->data[] = array(
								'Average speed:','<b>'.$log->avg_speed.'</b>',  
								'','',
								'Max Speed:','<b>'.$log->max_speed.'</b>', 
							);
		$table->data[] = array(
								'Average Heart Rate:','<b>'.$log->avg_hr.'</b>',  
								'','',
								'Max Heart Rate:','<b>'.$log->max_hr.'</b>', 
							);
		
		$table->data[] = array(
								'Average Pace:','<b>'.$log->avg_pace.'</b>',  
								'','',
								'Best Pace:','<b>'.$log->best_pace.'</b>', 
							);
							
		$table->data[] = array(
								'Vertical Up:','<b></b>',  
								'','',
								'Vertical Down:','<b></b>', 
							);

		$summary = print_table($table,true);

				
		if(!empty($log->notes)) {
			$summary .= "<br/>Notes: " . text_to_html($log->notes,false,false);
		}
		
		return $summary;
}

function generate_content($log,$feed_action='',$has_map_sessions=false) {
	$summary = "";
	
	if(empty($log->title)) {
			$log->title = 'Untitled ';
			if($log->activity) {
				$log->title .= ' --- ' . $log->activity;
			}
		}
		
		
		if(!empty($log->distance) and $log->distance > 0 and !empty($log->distance_unit)) {
			$log->title .= " (" . $log->distance . " " . $log->distance_unit . ")";
		}


		if($feed_action != 'mapFeed' and $has_map_sessions) {
			$log->title .= " -- [GPS]";
		}
		
		
		
		$dist = $log->distance;
		if($log->distance_unit) {
			$dist .= " " . $log->distance_unit;
		}
		
		
		
		$table = new stdClass();
	  	//$table->align = array('left', 'left');
	    $table->size = array('', '','100px', '', '','120px', '','');
	    $table->width = '*';
	    $table->data = array();
		$table->class = '';
		$table->extra_attrs = "border=\"0\" style=\"color: #555555; font-size: 12px;font-family: Arial, sans-serif;line-height: 16px;";
		$table->data[] = array(
								'Activity:','<b>'.$log->activity.'</b>',
								'','', 
								'Total Points:','<b>'.calculate_points($log).'</b>',
								'','',
								'Time in Zone 1:','<b>'.$log->z1_time.' / '.calculate_points($log,1).' pts</b>'
							);
		$table->data[] = array(
								'Date:','<b>'.$log->date.'</b>', 
								'','',
								'Time:','<b>'.$log->datetime.'</b>', 
								'','',
								'Time in Zone 2:','<b>'.$log->z2_time.' / '.calculate_points($log,2).' pts</b>'
							);
		$table->data[] = array(
								'Duration:','<b>'.$log->duration.'</b>',  
								'','',
								'Distance:','<b>'.$dist.'</b>', 
								'','',
								'Time in Zone 3:','<b>'.$log->z3_time.' / '.calculate_points($log,3).' pts</b>'
							);
		$table->data[] = array(
								'Average speed:','<b>'.$log->avg_speed.'</b>',  
								'','',
								'Max Speed:','<b>'.$log->max_speed.'</b>', 
								'','',
								'Time in Zone 4:','<b>'.$log->z4_time.' / '.calculate_points($log,4).' pts</b>'
							);
		$table->data[] = array(
								'Average Heart Rate:','<b>'.$log->avg_hr.'</b>',  
								'','',
								'Max Heart Rate:','<b>'.$log->max_hr.'</b>', 
								'','',
								'Time in Zone 5:','<b>'.$log->z5_time.' / '.calculate_points($log,5).' pts</b>'
							);
		
		$table->data[] = array(
								'Average Pace:','<b>'.$log->avg_pace.'</b>',  
								'','',
								'Best Pace:','<b>'.$log->best_pace.'</b>', 
								'','',
								'',''
							);
							
		$table->data[] = array(
								'Vertical Up:','<b></b>',  
								'','',
								'Vertical Down:','<b></b>', 
								'','',
								'',''
							);

		$summary = print_table($table,true);

				
		if(!empty($log->notes)) {
			$summary .= "<br/>Notes: " . text_to_html($log->notes,false,false);
		}
		
		return $summary;
}

/**
 * A class for making time periods readable.
 *
 * This class allows for the conversion of an integer
 * number of seconds into a readable string.
 * For example, '121' into '2 minutes, 1 second'.
 * 
 * If an array is passed to the class, the associative
 * keys are used for the names of the time segments.
 * For example, array('seconds' => 12, 'minutes' => 1)
 * into '1 minute, 12 seconds'.
 *
 * This class is plural aware. Time segments with values
 * other than 1 will have an 's' appended.
 * For example, '1 second' not '1 seconds'.
 *
 * @author      Aidan Lister <aidan@php.net>, Modified by Tristan Everitt
 * @version     1.2.1
 * @link        http://aidanlister.com/repos/v/Duration.php
 */
class Duration
{
    /**
     * All in one method
     *
     * @param   int|array  $duration  Array of time segments or a number of seconds
     * @return  string
     */
    function toString ($duration, $periods = null,$separator = ', ',$segment_name = true)
    {
        if (!is_array($duration)) {
            $duration = Duration::int2array($duration, $periods,$separator,true);
        }
 
        return Duration::array2string($duration,$separator,$segment_name);
    }
 
 
    /**
     * Return an array of date segments.
     *
     * @param        int $seconds Number of seconds to be parsed
     * @return       mixed An array containing named segments
     */
    function int2array ($seconds, $periods = null,$separator = ', ',$allperiods = false)
    {        
        // Define time periods
        if (!is_array($periods)) {
            $periods = array (
                    'years'     => 31556926,
                    'months'    => 2629743,
                    'weeks'     => 604800,
                    'days'      => 86400,
                    'hours'     => 3600,
                    'minutes'   => 60,
                    'seconds'   => 1
                    );
        }
 
        // Loop
        $seconds = (float) $seconds;
        foreach ($periods as $period => $value) {
            $count = floor($seconds / $value);
 
            if ($count == 0 and !$allperiods) {
                continue;
            }
 
            $values[$period] = $count;
            $seconds = $seconds % $value;
        }
 
        // Return
        if (empty($values)) {
            $values = null;
        }
 
        return $values;
    }
 
 
    /**
     * Return a string of time periods.
     *
     * @package      Duration
     * @param        mixed $duration An array of named segments
     * @return       string
     */
    function array2string ($duration,$separator = ', ',$use_segment_name = true)
    {
        if (!is_array($duration)) {
            return false;
        }
 
        foreach ($duration as $key => $value) {
            $segment_name = substr($key, 0, -1);
            $segment = $value;
            if($use_segment_name) {
            	$segment .= ' ' . $segment_name;
            }  
 
            // Plural
            if ($value != 1 and $use_segment_name) {
                $segment .= 's';
            }
 
            $array[] = $segment;
        }
 
        $str = implode($separator, $array);
        return $str;
    }
 
}

/*
https://www.nostinghosting.com/

Copyright 2008 Andy Moore (email : andy@andymoore.info)

SHARED SOURCE LICENSE

This License governs use of the accompanying Software, and your use of the Software constitutes acceptance of this license.

You may use this Software for any non-commercial purpose, subject to the restrictions in this license. Some purposes which can be non-commercial are teaching, academic research, and personal experimentation. You may also distribute this Software with books or other teaching materials, or publish the Software on websites, that are intended to teach the use of the Software.

You may not use or distribute this Software or any derivative works in any form for commercial purposes. Examples of commercial purposes would be running business operations, licensing, leasing, or selling the Software, or distributing the Software for use with commercial products.

You may modify this Software and distribute the modified Software for non-commercial purposes, however, you may not grant rights to the Software or derivative works that are broader than those provided by this License. For example, you may not distribute modifications of the Software under terms that would permit commercial use, or under terms that purport to require the Software or derivative works to be sublicensed to others.

You may use any information in intangible form that you remember after accessing the Software. However, this right does not grant you a license to any of Andy Moore's copyrights or patents for anything you might create using such information.

In return, we simply require that you agree:

   1. Not to remove any copyright or other notices from the Software.

   2. That if you distribute the Software in any form, you will include a verbatim copy of this license.

   3. That if you distribute derivative works of the Software in source code form you do so only under a license that includes all of the provisions of this License, and if you distribute derivative works of the Software solely in object form you do so only under a license that complies with this License.

   4. That if you have modified the Software or created derivative works, and distribute such modifications or derivative works, you will cause the modified files to carry prominent notices so that recipients know that they are not receiving the original Software. Such notices must state: (i) that you have changed the Software; and (ii) the date of any changes.

   5. THAT THE SOFTWARE COMES "AS IS", WITH NO WARRANTIES. THIS MEANS NO EXPRESS, IMPLIED OR STATUTORY WARRANTY, INCLUDING WITHOUT LIMITATION, WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE OR ANY WARRANTY OF TITLE OR NON-INFRINGEMENT. ALSO, YOU MUST PASS THIS DISCLAIMER ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.

   6. THAT ANDY MOORE WILL NOT BE LIABLE FOR ANY DAMAGES RELATED TO THE SOFTWARE OR THIS LICENSE, INCLUDING DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL OR INCIDENTAL DAMAGES, TO THE MAXIMUM EXTENT THE LAW PERMITS, NO MATTER WHAT LEGAL THEORY IT IS BASED ON. ALSO, YOU MUST PASS THIS LIMITATION OF LIABILITY ON WHENEVER YOU DISTRIBUTE THE SOFTWARE OR DERIVATIVE WORKS.

   7. That if you sue anyone over patents that you think may apply to the Software or anyone's use of the Software, your license to the Software ends automatically.

   8. That your rights under the License end automatically if you breach it in any way.

   9. Andy Moore reserves all rights not expressly granted to you in this license.

*/

function detect_mobile_device(){
  
  // check if the user agent value claims to be windows but not windows mobile
  if(stristr($_SERVER['HTTP_USER_AGENT'],'windows')&&!stristr($_SERVER['HTTP_USER_AGENT'],'windows ce')){
    return false;
  }
  // check if the user agent gives away any tell tale signs it's a mobile browser
  if(eregi('up.browser|up.link|windows ce|iemobile|mini|mmp|symbian|midp|wap|phone|pocket|mobile|pda|psp',$_SERVER['HTTP_USER_AGENT'])){
    return true;
  }
  // check the http accept header to see if wap.wml or wap.xhtml support is claimed
  if(stristr($_SERVER['HTTP_ACCEPT'],'text/vnd.wap.wml')||stristr($_SERVER['HTTP_ACCEPT'],'application/vnd.wap.xhtml+xml')){
    return true;
  }
  // check if there are any tell tales signs it's a mobile device from the _server headers
  if(isset($_SERVER['HTTP_X_WAP_PROFILE'])||isset($_SERVER['HTTP_PROFILE'])||isset($_SERVER['X-OperaMini-Features'])||isset($_SERVER['UA-pixels'])){
    return true;
  }
  // build an array with the first four characters from the most common mobile user agents
  $a = array(
                    'acs-'=>'acs-',
                    'alav'=>'alav',
                    'alca'=>'alca',
                    'amoi'=>'amoi',
                    'audi'=>'audi',
                    'aste'=>'aste',
                    'avan'=>'avan',
                    'benq'=>'benq',
                    'bird'=>'bird',
                    'blac'=>'blac',
                    'blaz'=>'blaz',
                    'brew'=>'brew',
                    'cell'=>'cell',
                    'cldc'=>'cldc',
                    'cmd-'=>'cmd-',
                    'dang'=>'dang',
                    'doco'=>'doco',
                    'eric'=>'eric',
                    'hipt'=>'hipt',
                    'inno'=>'inno',
                    'ipaq'=>'ipaq',
                    'java'=>'java',
                    'jigs'=>'jigs',
                    'kddi'=>'kddi',
                    'keji'=>'keji',
                    'leno'=>'leno',
                    'lg-c'=>'lg-c',
                    'lg-d'=>'lg-d',
                    'lg-g'=>'lg-g',
                    'lge-'=>'lge-',
                    'maui'=>'maui',
                    'maxo'=>'maxo',
                    'midp'=>'midp',
                    'mits'=>'mits',
                    'mmef'=>'mmef',
                    'mobi'=>'mobi',
                    'mot-'=>'mot-',
                    'moto'=>'moto',
                    'mwbp'=>'mwbp',
                    'nec-'=>'nec-',
                    'newt'=>'newt',
                    'noki'=>'noki',
                    'opwv'=>'opwv',
                    'palm'=>'palm',
                    'pana'=>'pana',
                    'pant'=>'pant',
                    'pdxg'=>'pdxg',
                    'phil'=>'phil',
                    'play'=>'play',
                    'pluc'=>'pluc',
                    'port'=>'port',
                    'prox'=>'prox',
                    'qtek'=>'qtek',
                    'qwap'=>'qwap',
                    'sage'=>'sage',
                    'sams'=>'sams',
                    'sany'=>'sany',
                    'sch-'=>'sch-',
                    'sec-'=>'sec-',
                    'send'=>'send',
                    'seri'=>'seri',
                    'sgh-'=>'sgh-',
                    'shar'=>'shar',
                    'sie-'=>'sie-',
                    'siem'=>'siem',
                    'smal'=>'smal',
                    'smar'=>'smar',
                    'sony'=>'sony',
                    'sph-'=>'sph-',
                    'symb'=>'symb',
                    't-mo'=>'t-mo',
                    'teli'=>'teli',
                    'tim-'=>'tim-',
                    'tosh'=>'tosh',
                    'treo'=>'treo',
                    'tsm-'=>'tsm-',
                    'upg1'=>'upg1',
                    'upsi'=>'upsi',
                    'vk-v'=>'vk-v',
                    'voda'=>'voda',
                    'wap-'=>'wap-',
                    'wapa'=>'wapa',
                    'wapi'=>'wapi',
                    'wapp'=>'wapp',
                    'wapr'=>'wapr',
                    'webc'=>'webc',
                    'winw'=>'winw',
                    'winw'=>'winw',
                    'xda-'=>'xda-'
                  );
  // check if the first four characters of the current user agent are set as a key in the array
  if(isset($a[substr($_SERVER['HTTP_USER_AGENT'],0,4)])){
    return true;
  }
}

function detect_iphone(){
  if(eregi('iphone',$_SERVER['HTTP_USER_AGENT'])||eregi('ipod',$_SERVER['HTTP_USER_AGENT'])){
    return true;
  }
}

?>
